home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / zaxxon.c < prev    next >
C/C++ Source or Header  |  2000-01-10  |  15KB  |  507 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12.  
  13. unsigned char *zaxxon_char_color_bank;
  14. unsigned char *zaxxon_background_position;
  15. unsigned char *zaxxon_background_color_bank;
  16. unsigned char *zaxxon_background_enable;
  17. static struct osd_bitmap *backgroundbitmap1,*backgroundbitmap2;
  18. static const unsigned char *color_codes;
  19.  
  20. int zaxxon_vid_type;    /* set by init_machine; 0 = zaxxon; 1 = congobongo */
  21.  
  22. #define ZAXXON_VID    0
  23. #define CONGO_VID    1
  24. #define FUTSPY_VID    2
  25.  
  26.  
  27. void zaxxon_vh_stop(void);
  28.  
  29.  
  30. /***************************************************************************
  31.  
  32.   Convert the color PROMs into a more useable format.
  33.  
  34.   Zaxxon has one 256x8 palette PROM and one 256x4 PROM which contains the
  35.   color codes to use for characters on a per row/column basis (groups of
  36.   of 4 characters in the same row).
  37.   Congo Bongo has similar hardware, but it has color RAM instead of the
  38.   lookup PROM.
  39.  
  40.   The palette PROM is connected to the RGB output this way:
  41.  
  42.   bit 7 -- 220 ohm resistor  -- BLUE
  43.         -- 470 ohm resistor  -- BLUE
  44.         -- 220 ohm resistor  -- GREEN
  45.         -- 470 ohm resistor  -- GREEN
  46.         -- 1  kohm resistor  -- GREEN
  47.         -- 220 ohm resistor  -- RED
  48.         -- 470 ohm resistor  -- RED
  49.   bit 0 -- 1  kohm resistor  -- RED
  50.  
  51. ***************************************************************************/
  52. void zaxxon_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
  53. {
  54.     int i;
  55.     #define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
  56.     #define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
  57.  
  58.  
  59.     for (i = 0;i < Machine->drv->total_colors;i++)
  60.     {
  61.         int bit0,bit1,bit2;
  62.  
  63.  
  64.         /* red component */
  65.         bit0 = (*color_prom >> 0) & 0x01;
  66.         bit1 = (*color_prom >> 1) & 0x01;
  67.         bit2 = (*color_prom >> 2) & 0x01;
  68.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  69.         /* green component */
  70.         bit0 = (*color_prom >> 3) & 0x01;
  71.         bit1 = (*color_prom >> 4) & 0x01;
  72.         bit2 = (*color_prom >> 5) & 0x01;
  73.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  74.         /* blue component */
  75.         bit0 = 0;
  76.         bit1 = (*color_prom >> 6) & 0x01;
  77.         bit2 = (*color_prom >> 7) & 0x01;
  78.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  79.  
  80.         color_prom++;
  81.     }
  82.  
  83.  
  84.     /* color_prom now points to the beginning of the character color codes */
  85.     color_codes = color_prom;    /* we'll need it later */
  86.  
  87.  
  88.     /* all gfx elements use the same palette */
  89.     for (i = 0;i < TOTAL_COLORS(0);i++)
  90.         COLOR(0,i) = i;
  91. }
  92.  
  93. /***************************************************************************
  94.  
  95.   Start the video hardware emulation.
  96.  
  97. ***************************************************************************/
  98.  
  99. static void copy_pixel(struct osd_bitmap *dst_bm, int dx, int dy,
  100.                        struct osd_bitmap *src_bm, int sx, int sy)
  101. {
  102.     plot_pixel(dst_bm, dx, dy, read_pixel(src_bm, sx, sy));
  103. }
  104.  
  105.  
  106. static void create_background(struct osd_bitmap *dst_bm, struct osd_bitmap *src_bm, int col)
  107. {
  108.     int offs;
  109.     int sx,sy;
  110.  
  111.  
  112.     for (offs = 0;offs < 0x4000;offs++)
  113.     {
  114.         sy = 8 * (offs / 32);
  115.         sx = 8 * (offs % 32);
  116.  
  117.         if (!(Machine->orientation & ORIENTATION_SWAP_XY))
  118.             /* leave screenful of black pixels at end */
  119.             sy += 256;
  120.  
  121.         drawgfx(src_bm,Machine->gfx[1],
  122.                 memory_region(REGION_GFX4)[offs] + 256 * (memory_region(REGION_GFX4)[0x4000 + offs] & 3),
  123.                 col + (memory_region(REGION_GFX4)[0x4000 + offs] >> 4),
  124.                 0,0,
  125.                 sx,sy,
  126.                 0,TRANSPARENCY_NONE,0);
  127.     }
  128.  
  129.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  130.     {
  131.         /* the background is stored as a rectangle, but is drawn by the hardware skewed: */
  132.         /* go right two pixels, then up one pixel. Doing the conversion at run time would */
  133.         /* be extremely expensive, so we do it now. To save memory, we squash the image */
  134.         /* horizontally (doing line shifts at run time is much less expensive than doing */
  135.         /* column shifts) */
  136.         for (offs = -510;offs < 4096;offs += 2)
  137.         {
  138.             sx = (2302-510/2) - offs/2;
  139.  
  140.             for (sy = 0;sy < 512;sy += 2)
  141.             {
  142.                 if (offs + sy >= 0 && offs + sy < 4096)
  143.                 {
  144.                     copy_pixel (dst_bm, sx, 511 -  sy   ,    src_bm, sy/2, 4095 - (offs+sy));
  145.                     copy_pixel (dst_bm, sx, 511 - (sy+1), src_bm, sy/2, 4095 - (offs+sy+1));
  146.                 }
  147.             }
  148.         }
  149.     }
  150. }
  151.  
  152.  
  153. int zaxxon_vh_start(void)
  154. {
  155.     struct osd_bitmap *prebitmap;
  156.     int width, height;
  157.  
  158.  
  159.     if (generic_vh_start() != 0)
  160.         return 1;
  161.  
  162.     /* for speed, backgrounds are arranged differently if axis is swapped */
  163.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  164.         height = 512, width = 2303+32;
  165.     else
  166.         /* leave a screenful of black pixels at each end */
  167.         height = 256+4096+256, width = 256;
  168.  
  169.     /* large bitmap for the precalculated background */
  170.     if ((backgroundbitmap1 = osd_create_bitmap(width,height)) == 0)
  171.     {
  172.         zaxxon_vh_stop();
  173.         return 1;
  174.     }
  175.  
  176.     if (zaxxon_vid_type == ZAXXON_VID || zaxxon_vid_type == FUTSPY_VID)
  177.     {
  178.         if ((backgroundbitmap2 = osd_create_bitmap(width,height)) == 0)
  179.         {
  180.             zaxxon_vh_stop();
  181.             return 1;
  182.         }
  183.     }
  184.  
  185.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  186.     {
  187.         /* create a temporary bitmap to prepare the background before converting it */
  188.         if ((prebitmap = osd_create_bitmap(256,4096)) == 0)
  189.         {
  190.             zaxxon_vh_stop();
  191.             return 1;
  192.         }
  193.     }
  194.     else
  195.         prebitmap = backgroundbitmap1;
  196.  
  197.     /* prepare the background */
  198.     create_background(backgroundbitmap1, prebitmap, 0);
  199.  
  200.     if (zaxxon_vid_type == ZAXXON_VID || zaxxon_vid_type == FUTSPY_VID)
  201.     {
  202.         if (!(Machine->orientation & ORIENTATION_SWAP_XY))
  203.             prebitmap = backgroundbitmap2;
  204.  
  205.         /* prepare a second background with different colors, used in the death sequence */
  206.         create_background(backgroundbitmap2, prebitmap, 16);
  207.     }
  208.  
  209.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  210.         osd_free_bitmap(prebitmap);
  211.  
  212.     return 0;
  213. }
  214.  
  215. int razmataz_vh_start(void)
  216. {
  217.     int offs;
  218.  
  219.  
  220.     if (generic_vh_start() != 0)
  221.         return 1;
  222.  
  223.     /* large bitmap for the precalculated background */
  224.     if ((backgroundbitmap1 = osd_create_bitmap(256,4096)) == 0)
  225.     {
  226.         zaxxon_vh_stop();
  227.         return 1;
  228.     }
  229.  
  230.     if ((backgroundbitmap2 = osd_create_bitmap(256,4096)) == 0)
  231.     {
  232.         zaxxon_vh_stop();
  233.         return 1;
  234.     }
  235.  
  236.  
  237.     /* prepare the background */
  238.     for (offs = 0;offs < 0x4000;offs++)
  239.     {
  240.         int sx,sy;
  241.  
  242.  
  243.         sy = 8 * (offs / 32);
  244.         sx = 8 * (offs % 32);
  245.  
  246.         drawgfx(backgroundbitmap1,Machine->gfx[1],
  247.                 memory_region(REGION_GFX4)[offs] + 256 * (memory_region(REGION_GFX4)[0x4000 + offs] & 3),
  248.                 memory_region(REGION_GFX4)[0x4000 + offs] >> 4,
  249.                 0,0,
  250.                 sx,sy,
  251.                 0,TRANSPARENCY_NONE,0);
  252.  
  253.         drawgfx(backgroundbitmap2,Machine->gfx[1],
  254.                 memory_region(REGION_GFX4)[offs] + 256 * (memory_region(REGION_GFX4)[0x4000 + offs] & 3),
  255.                 16 + (memory_region(REGION_GFX4)[0x4000 + offs] >> 4),
  256.                 0,0,
  257.                 sx,sy,
  258.                 0,TRANSPARENCY_NONE,0);
  259.     }
  260.  
  261.     return 0;
  262. }
  263.  
  264.  
  265.  
  266. /***************************************************************************
  267.  
  268.   Stop the video hardware emulation.
  269.  
  270. ***************************************************************************/
  271. void zaxxon_vh_stop(void)
  272. {
  273.     if (backgroundbitmap1)  osd_free_bitmap(backgroundbitmap1);
  274.     if (backgroundbitmap2)  osd_free_bitmap(backgroundbitmap2);
  275.     generic_vh_stop();
  276. }
  277.  
  278.  
  279. /***************************************************************************
  280.  
  281.   Draw the game screen in the given osd_bitmap.
  282.   Do NOT call osd_update_display() from this function, it will be called by
  283.   the main emulation engine.
  284.  
  285. ***************************************************************************/
  286.  
  287. static void draw_sprites(struct osd_bitmap *bitmap)
  288. {
  289.     int offs;
  290.  
  291.     if (zaxxon_vid_type == CONGO_VID)
  292.     {
  293.         int i;
  294.         static unsigned int sprpri[0x100]; /* this really should not be more
  295.                                      * than 0x1e, but I did not want to check
  296.                                      * for 0xff which is set when sprite is off
  297.                                      * -V-
  298.                                      */
  299.  
  300.         /* Draw the sprites. Note that it is important to draw them exactly in this */
  301.         /* order, to have the correct priorities. */
  302.         /* Sprites actually start at 0xff * [0xc031], it seems to be static tho'*/
  303.         /* The number of active sprites is stored at 0xc032 */
  304.  
  305.         for (offs = 0x1e * 0x20 ;offs >= 0x00 ;offs -= 0x20)
  306.             sprpri[ spriteram[offs+1] ] = offs;
  307.  
  308.         for (i=0x1e ; i>=0; i--)
  309.         {
  310.             offs = sprpri[i];
  311.  
  312.             if (spriteram[offs+2] != 0xff)
  313.             {
  314.                 drawgfx(bitmap,Machine->gfx[2],
  315.                         spriteram[offs+2+1]& 0x7f,
  316.                         spriteram[offs+2+2],
  317.                         spriteram[offs+2+2] & 0x80,spriteram[offs+2+1] & 0x80,
  318.                         ((spriteram[offs+2+3] + 16) & 0xff) - 31,255 - spriteram[offs+2] - 15,
  319.                         &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  320.             }
  321.         }
  322.     }
  323.     else if (zaxxon_vid_type == FUTSPY_VID)
  324.     {
  325.         /* Draw the sprites. Note that it is important to draw them exactly in this */
  326.         /* order, to have the correct priorities. */
  327.         for (offs = spriteram_size - 4;offs >= 0;offs -= 4)
  328.         {
  329.             if (spriteram[offs] != 0xff)
  330.             {
  331.                     drawgfx(bitmap,Machine->gfx[2],
  332.                         spriteram[offs+1] & 0x7f,
  333.                         spriteram[offs+2] & 0x3f,
  334.                         spriteram[offs+1] & 0x80,spriteram[offs+1] & 0x80,    /* ?? */
  335.                         ((spriteram[offs+3] + 16) & 0xff) - 32,255 - spriteram[offs] - 16,
  336.                         &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  337.             }
  338.         }
  339.     }
  340.     else
  341.     {
  342.         /* Draw the sprites. Note that it is important to draw them exactly in this */
  343.         /* order, to have the correct priorities. */
  344.         for (offs = spriteram_size - 4;offs >= 0;offs -= 4)
  345.         {
  346.             if (spriteram[offs] != 0xff)
  347.             {
  348.                     drawgfx(bitmap,Machine->gfx[2],
  349.                         spriteram[offs+1] & 0x3f,
  350.                         spriteram[offs+2] & 0x3f,
  351.                         spriteram[offs+1] & 0x40,spriteram[offs+1] & 0x80,
  352.                         ((spriteram[offs+3] + 16) & 0xff) - 32,255 - spriteram[offs] - 16,
  353.                         &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  354.             }
  355.         }
  356.     }
  357. }
  358.  
  359. void zaxxon_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  360. {
  361.     int offs;
  362.  
  363.  
  364.     /* copy the background */
  365.     /* TODO: there's a bug here which shows only in test mode. The background doesn't */
  366.     /* cover the whole screen, so the image is not fully overwritten and part of the */
  367.     /* character color test screen remains on screen when it is replaced by the background */
  368.     /* color test. */
  369.     if (*zaxxon_background_enable)
  370.     {
  371.         int i,skew,scroll;
  372.         struct rectangle clip;
  373.  
  374.  
  375.         if (Machine->orientation & ORIENTATION_SWAP_XY)
  376.         {
  377.             /* standard rotation - skew background horizontally */
  378.             if (zaxxon_vid_type == CONGO_VID)
  379.                 scroll = 1023+63 - (zaxxon_background_position[0] + 256*zaxxon_background_position[1]);
  380.             else
  381.                 scroll = 2048+63 - (zaxxon_background_position[0] + 256*(zaxxon_background_position[1]&7));
  382.  
  383.             skew = 128 - 512 + 2 * Machine->drv->visible_area.min_x;
  384.  
  385.             clip.min_y = Machine->drv->visible_area.min_y;
  386.             clip.max_y = Machine->drv->visible_area.max_y;
  387.  
  388.             for (i = Machine->drv->visible_area.min_x;i <= Machine->drv->visible_area.max_x;i++)
  389.             {
  390.                 clip.min_x = i;
  391.                 clip.max_x = i;
  392.  
  393.                 if ((zaxxon_vid_type == ZAXXON_VID || zaxxon_vid_type == FUTSPY_VID)
  394.                      && (*zaxxon_background_color_bank & 1))
  395.                     copybitmap(bitmap,backgroundbitmap2,0,0,-scroll,skew,&clip,TRANSPARENCY_NONE,0);
  396.                 else
  397.                     copybitmap(bitmap,backgroundbitmap1,0,0,-scroll,skew,&clip,TRANSPARENCY_NONE,0);
  398.  
  399.                 skew += 2;
  400.             }
  401.         }
  402.         else
  403.         {
  404.             /* skew background up one pixel every 2 horizontal pixels */
  405.             if (zaxxon_vid_type == CONGO_VID)
  406.                 scroll = 2050 + 2*(zaxxon_background_position[0] + 256*zaxxon_background_position[1])
  407.                     - backgroundbitmap1->height + 256;
  408.             else
  409.                 scroll = 2*(zaxxon_background_position[0] + 256*(zaxxon_background_position[1]&7))
  410.                     - backgroundbitmap1->height + 256;
  411.  
  412.             skew = 72 - (255 - Machine->drv->visible_area.max_y);
  413.  
  414.             clip.min_x = Machine->drv->visible_area.min_x;
  415.             clip.max_x = Machine->drv->visible_area.max_x;
  416.  
  417.             for (i = Machine->drv->visible_area.max_y;i >= Machine->drv->visible_area.min_y;i-=2)
  418.             {
  419.                 clip.min_y = i-1;
  420.                 clip.max_y = i;
  421.  
  422.                 if ((zaxxon_vid_type == ZAXXON_VID || zaxxon_vid_type == FUTSPY_VID)
  423.                      && (*zaxxon_background_color_bank & 1))
  424.                     copybitmap(bitmap,backgroundbitmap2,0,0,skew,scroll,&clip,TRANSPARENCY_NONE,0);
  425.                 else
  426.                     copybitmap(bitmap,backgroundbitmap1,0,0,skew,scroll,&clip,TRANSPARENCY_NONE,0);
  427.  
  428.                 skew--;
  429.             }
  430.         }
  431.     }
  432.     else fillbitmap(bitmap,Machine->pens[0],&Machine->drv->visible_area);
  433.  
  434.  
  435.     draw_sprites(bitmap);
  436.  
  437.  
  438.     /* draw the frontmost playfield. They are characters, but draw them as sprites */
  439.     for (offs = videoram_size - 1;offs >= 0;offs--)
  440.     {
  441.         int sx,sy;
  442.         int color;
  443.  
  444.  
  445.         sy = offs / 32;
  446.         sx = offs % 32;
  447.  
  448.         if (zaxxon_vid_type == CONGO_VID)
  449.             color = colorram[offs];
  450.         else
  451.             /* not sure about the color code calculation - char_color_bank is used only in test mode */
  452.             color =    (color_codes[sx + 32 * (sy/4)] & 0x0f) + 16 * (*zaxxon_char_color_bank & 1);
  453.  
  454.         drawgfx(bitmap,Machine->gfx[0],
  455.                 videoram[offs],
  456.                 color,
  457.                 0,0,
  458.                 8*sx,8*sy,
  459.                 &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  460.     }
  461. }
  462.  
  463. void razmataz_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  464. {
  465.     int offs;
  466.  
  467.  
  468.     /* copy the background */
  469.     if (*zaxxon_background_enable)
  470.     {
  471.         int scroll;
  472.  
  473.         scroll = 2*(zaxxon_background_position[0] + 256*(zaxxon_background_position[1]&7));
  474.  
  475.         if (*zaxxon_background_color_bank & 1)
  476.             copyscrollbitmap(bitmap,backgroundbitmap2,0,0,1,&scroll,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  477.         else
  478.             copyscrollbitmap(bitmap,backgroundbitmap1,0,0,1,&scroll,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  479.     }
  480.     else fillbitmap(bitmap,Machine->pens[0],&Machine->drv->visible_area);
  481.  
  482.  
  483.     draw_sprites(bitmap);
  484.  
  485.  
  486.     /* draw the frontmost playfield. They are characters, but draw them as sprites */
  487.     for (offs = videoram_size - 1;offs >= 0;offs--)
  488.     {
  489.         int sx,sy;
  490.         int code,color;
  491.  
  492.  
  493.         sx = offs % 32;
  494.         sy = offs / 32;
  495.  
  496.         code = videoram[offs];
  497.         color =    (color_codes[code] & 0x0f) + 16 * (*zaxxon_char_color_bank & 1);
  498.  
  499.         drawgfx(bitmap,Machine->gfx[0],
  500.                 code,
  501.                 color,
  502.                 0,0,
  503.                 8*sx,8*sy,
  504.                 &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  505.     }
  506. }
  507.